package com.service.api.google;


import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.rpc.ServiceException;

import com.google.api.adwords.lib.AdWordsService;
import com.google.api.adwords.lib.AdWordsServiceLogger;
import com.google.api.adwords.lib.AdWordsUser;
import com.google.api.adwords.v201209.cm.ApiException;
import com.google.api.adwords.v201209.cm.Criterion;
import com.google.api.adwords.v201209.cm.Keyword;
import com.google.api.adwords.v201209.cm.KeywordMatchType;
import com.google.api.adwords.v201209.cm.Language;
import com.google.api.adwords.v201209.cm.Location;
import com.google.api.adwords.v201209.cm.Money;
import com.google.api.adwords.v201209.o.AdGroupEstimateRequest;
import com.google.api.adwords.v201209.o.CampaignEstimateRequest;
import com.google.api.adwords.v201209.o.KeywordEstimate;
import com.google.api.adwords.v201209.o.KeywordEstimateRequest;
import com.google.api.adwords.v201209.o.TrafficEstimatorResult;
import com.google.api.adwords.v201209.o.TrafficEstimatorSelector;
import com.google.api.adwords.v201209.o.TrafficEstimatorServiceInterface;
import com.pub.i.AttributesI;
import com.pub.util.MathUtil;
import com.service.vo.KeywordVo;


public class GetTrafficEstimates implements AttributesI 
{
	private AdWordsUser user;
	
	private TrafficEstimatorServiceInterface trafficEstimatorService;
	
	public GetTrafficEstimates(AdWordsUser user)
	{
		this.user = user;
	}
	
	public void init() throws ServiceException
	{
		trafficEstimatorService = user.getService(AdWordsService.V201209.TRAFFIC_ESTIMATOR_SERVICE);
			
		// Log SOAP XML request and response.
		AdWordsServiceLogger.log();		
	}
	
	public Map<String, KeywordVo> getTrafficEstimates(Map<String, KeywordVo> keywords, KeywordMatchType matchType) throws ApiException, RemoteException 
	{
		if(keywords == null || keywords.size() == 0)
			return keywords;

		// Create keywords. Up to 2000 keywords can be passed in a single request.
		List<Keyword> keywordList = new ArrayList<Keyword>();
		
		for(Entry<String, KeywordVo> entry: keywords.entrySet()){
			keywordList.add(new Keyword(null, null, null, entry.getKey(), matchType));
	    }
		
		// Create a keyword estimate request for each keyword.
		List<KeywordEstimateRequest> keywordEstimateRequests = new ArrayList<KeywordEstimateRequest>();
		for (Keyword keyword : keywordList) {
			KeywordEstimateRequest keywordEstimateRequest = new KeywordEstimateRequest();
			keywordEstimateRequest.setKeyword(keyword);
			keywordEstimateRequests.add(keywordEstimateRequest);
		}

		// Create ad group estimate requests.
		List<AdGroupEstimateRequest> adGroupEstimateRequests 	= new ArrayList<AdGroupEstimateRequest>();
		AdGroupEstimateRequest adGroupEstimateRequest 			= new AdGroupEstimateRequest();
		
		adGroupEstimateRequest.setKeywordEstimateRequests(keywordEstimateRequests.toArray(new KeywordEstimateRequest[]{}));
		adGroupEstimateRequest.setMaxCpc(new Money(null, 20000000L));
		adGroupEstimateRequests.add(adGroupEstimateRequest);

		// Create campaign estimate requests.
		List<CampaignEstimateRequest> campaignEstimateRequests 	= new ArrayList<CampaignEstimateRequest>();
		CampaignEstimateRequest campaignEstimateRequest 		= new CampaignEstimateRequest();
		
		campaignEstimateRequest.setAdGroupEstimateRequests(adGroupEstimateRequests.toArray(new AdGroupEstimateRequest[]{}));
		campaignEstimateRequests.add(campaignEstimateRequest);

	    Location unitedStates = new Location();
	    unitedStates.setId(2840L);
	    Language english = new Language();
	    english.setId(1000L);
	    campaignEstimateRequest.setCriteria(new Criterion[]{unitedStates, english});

		// Create selector.
		TrafficEstimatorSelector selector = new TrafficEstimatorSelector();
		selector.setCampaignEstimateRequests(campaignEstimateRequests.toArray(new CampaignEstimateRequest[]{}));

		// Get traffic estimates.
		TrafficEstimatorResult result = trafficEstimatorService.get(selector);

		// Display traffic estimates.
		if (result != null && result.getCampaignEstimates() != null) {
			Double meanAverageCpc;
			Double meanTotalCost;
			
			Double meanAveragePosition;
			Double clicks;
			
			Keyword keyword;
			KeywordEstimate keywordEstimate;
			
			KeywordVo vo;
			
			KeywordEstimate[] keywordEstimates = result.getCampaignEstimates()[0].getAdGroupEstimates()[0].getKeywordEstimates();
	        for (int i = 0; i < keywordEstimates.length; i++) {
	        	keyword 		= keywordEstimateRequests.get(i).getKeyword();
	        	keywordEstimate = keywordEstimates[i];
	
	        	// Find the mean of the min and max values.
	        	meanAverageCpc 		= MathUtil.round((keywordEstimate.getMin().getAverageCpc().getMicroAmount() + keywordEstimate.getMax().getAverageCpc().getMicroAmount()) / 2.0 / 1000000, 4);
	        	meanAveragePosition = MathUtil.round((keywordEstimate.getMin().getAveragePosition() + keywordEstimate.getMax().getAveragePosition()) / 2.0, 4);
	        	clicks 				= MathUtil.round((keywordEstimate.getMin().getClicksPerDay() + keywordEstimate.getMax().getClicksPerDay()) / 2.0, 4);
	        	meanTotalCost 		= MathUtil.round((keywordEstimate.getMin().getTotalCost().getMicroAmount() + keywordEstimate.getMax().getTotalCost().getMicroAmount()) / 2.0, 4);
	
	        	if(keywords.containsKey(keyword.getText())){
	        		vo = keywords.get(keyword.getText());
	        		
	        		vo.put(AttributesI.ESTIMATES_AVERAGE_CPC, String.format("%.4f", meanAverageCpc));
	        		vo.put(AttributesI.ESTIMATES_AVERAGE_POSITION, String.format("%.4f", meanAveragePosition));
	        		vo.put(AttributesI.ESTIMATES_AVERAGE_CLICKS, String.format("%.4f", clicks));
	        		vo.put(AttributesI.ESTIMATES_TOTAL_COST, String.format("%.4f", meanTotalCost));
	        	}
	        }
		} else {
			System.out.println("no traffic estimates were returned.");
		}
		
		return keywords;
	}
	
	public KeywordVo getTrafficEstimates(KeywordVo keywords, KeywordMatchType matchType) throws ApiException, RemoteException 
	{
		if(keywords == null)
			return keywords;

		// Create keywords. Up to 2000 keywords can be passed in a single request.
		List<Keyword> keywordList = new ArrayList<Keyword>();
		
		
		keywordList.add(new Keyword(null, null, null, keywords.getKeyword(), matchType));
	    
		
		// Create a keyword estimate request for each keyword.
		List<KeywordEstimateRequest> keywordEstimateRequests = new ArrayList<KeywordEstimateRequest>();
		for (Keyword keyword : keywordList) {
			KeywordEstimateRequest keywordEstimateRequest = new KeywordEstimateRequest();
			keywordEstimateRequest.setKeyword(keyword);
			keywordEstimateRequests.add(keywordEstimateRequest);
		}

		// Create ad group estimate requests.
		List<AdGroupEstimateRequest> adGroupEstimateRequests 	= new ArrayList<AdGroupEstimateRequest>();
		AdGroupEstimateRequest adGroupEstimateRequest 			= new AdGroupEstimateRequest();
		
		adGroupEstimateRequest.setKeywordEstimateRequests(keywordEstimateRequests.toArray(new KeywordEstimateRequest[]{}));
		adGroupEstimateRequest.setMaxCpc(new Money(null, 1000000L));
		adGroupEstimateRequests.add(adGroupEstimateRequest);

		// Create campaign estimate requests.
		List<CampaignEstimateRequest> campaignEstimateRequests 	= new ArrayList<CampaignEstimateRequest>();
		CampaignEstimateRequest campaignEstimateRequest 		= new CampaignEstimateRequest();
		
		campaignEstimateRequest.setAdGroupEstimateRequests(adGroupEstimateRequests.toArray(new AdGroupEstimateRequest[]{}));
		campaignEstimateRequests.add(campaignEstimateRequest);

	    Location unitedStates = new Location();
	    unitedStates.setId(2840L);
	    Language english = new Language();
	    english.setId(1000L);
	    campaignEstimateRequest.setCriteria(new Criterion[]{unitedStates, english});

		// Create selector.
		TrafficEstimatorSelector selector = new TrafficEstimatorSelector();
		selector.setCampaignEstimateRequests(campaignEstimateRequests.toArray(new CampaignEstimateRequest[]{}));

		// Get traffic estimates.
		TrafficEstimatorResult result = trafficEstimatorService.get(selector);

		// Display traffic estimates.
		if (result != null && result.getCampaignEstimates() != null) {
			Double meanAverageCpc;
			Double meanTotalCost;
			
			Double meanAveragePosition;
			Double averageclicks;
			
			Keyword keyword;
			KeywordEstimate keywordEstimate;
			
			KeywordEstimate[] keywordEstimates = result.getCampaignEstimates()[0].getAdGroupEstimates()[0].getKeywordEstimates();
	        for (int i = 0; i < keywordEstimates.length; i++) {
	        	keyword 		= keywordEstimateRequests.get(i).getKeyword();
	        	keywordEstimate = keywordEstimates[i];
	
	        	// Find the mean of the min and max values.
	        	meanAverageCpc 		= MathUtil.round((keywordEstimate.getMin().getAverageCpc().getMicroAmount() + keywordEstimate.getMax().getAverageCpc().getMicroAmount()) / 2.0 / 1000000, 4);
	        	meanAveragePosition = MathUtil.round((keywordEstimate.getMin().getAveragePosition() + keywordEstimate.getMax().getAveragePosition()) / 2.0, 4);
	        	averageclicks 		= MathUtil.round((keywordEstimate.getMin().getClicksPerDay() + keywordEstimate.getMax().getClicksPerDay()) / 2.0, 4);
	        	meanTotalCost 		= MathUtil.round((keywordEstimate.getMin().getTotalCost().getMicroAmount() + keywordEstimate.getMax().getTotalCost().getMicroAmount()) / 2.0, 4);
	
	        	if(keywords.getKeyword().equalsIgnoreCase(keyword.getText())){
        			keywords.put(AttributesI.ESTIMATES_AVERAGE_CPC, String.format("%.4f", meanAverageCpc));
        			keywords.put(AttributesI.ESTIMATES_AVERAGE_POSITION, String.format("%.4f", meanAveragePosition));
        			keywords.put(AttributesI.ESTIMATES_AVERAGE_CLICKS, String.format("%.4f", averageclicks));
        			keywords.put(AttributesI.ESTIMATES_TOTAL_COST, String.format("%.4f", meanTotalCost));
        		}
	        }
		} else {
			System.out.println("No traffic estimates were returned.");
		}
		
		return keywords;
	}
	
	
}
